// GummyBear ^_^
// command.cpp

#include <iostream>
#include <unistd.h>
#include <sstream>

#include "command.h"

command::command(std::string key) {
  keyWord = key;
  titleHead = nullptr;
  obj = "";
  objName = "";
  insertValue = "";
}

void command::_error() {
  std::cout << "Something wrong happened when excecuting command." << std::endl;
}

bool command::_create() {
  // Creating 
  std::string str = "DATA/" + objName;
  if (access(str.c_str(), F_OK) != 0) {
    str = "mkdir " + str;
    system(str.c_str());
    std::cout << "Database " << objName << " created." << std::endl;
  }
    else 
      std::cout << "Database " << objName << " has already exist." << std::endl;
  
  return true;
}

bool command::_drop() {
  // Droping 
  std::string str = "DATA/" + objName;
  if (access(str.c_str(), F_OK) == 0) {
    str = "rm -rf " + str;
    system(str.c_str());
    std::cout << "Database " << objName << " has been dropped." << std::endl;
    if(!objName.compare(curDB.c_str())) 
      curDB = "";
  } 
  else
    std::cout << "Database " << objName << " doesn't exist." << std::endl;
  
  return true;
}

bool command::_use() {
  std::string str = "DATA/" + objName;
  if (access(str.c_str(), F_OK) == 0 ) {
    std::cout << "Switch to database " << objName << std::endl;
    curDB = objName;
  }
  else {
    std::cout << "Database " << objName << "doesn't exist." << std::endl;
  }

  return true;
}

bool command::_createTable() {
  // Creating 
  
  std::string address;
  address = "DATA/" + curDB + "/" + objName + ".dat";
  if (access(address.c_str(), F_OK) == 0) {
    std::cout << "Table " << objName << " is already exist." << std::endl;
    return false;
  }

  table t(titleHead, objName);
  t.tableSave();

  return true;
}

bool command::_droptable() {
  //Droping 
  std::cout << "Droping table " << objName << std::endl;
  std::string address;
  address = "DATA/" + curDB + "/" + objName + ".dat";
  if (access(address.c_str(), F_OK) != 0) {
    std::cout << "Table " << objName << " doesn't exist." << std::endl;
    return false;
  } else {
    address = "rm " + address;
    system(address.c_str());
  }
  return true;
}

bool command::_insert() {
  std::string address = "DATA/" + curDB + "/" + objName + ".dat";
  if (access(address.c_str(), F_OK) != 0) {
    std::cout << "Table " << address << " doesn't exist." << std::endl;
    return false;
  }
  table *t = (table*) new table(address);

  insertValue = insertValue.substr(1, insertValue.length() - 2);
  t->rowNumber++;
  titleNode* head = t->tabletitle->next;
  std::istringstream splitStream(insertValue);
  std::string singleWord;

  int i = 0;
  for(i = 0; i < defaultLength && t->isFull[i] != 0; i++);
  while(head != nullptr) {
    splitStream >> singleWord;
    singleWord = singleWord.substr(0, singleWord.length() - 1);
    if (!head->titleType.compare("char")) {
      head->strPtr[i] = singleWord;
      t->isFull[i] = 1;
    } else {
      head->intPtr[i] = std::stoi(singleWord);
      t->isFull[i] = 1;
    }
    head = head -> next;
  }

  t->tableSave();
  return true;
}

bool command::_select() {
  //Todo

  return true;
}

bool command::_delete() {
  //Todo

  return true;
}

bool command::excecute() {

  // CREATE
  if (!keyWord.compare("create")) {

    // CREATE DATABASE
    if (!obj.compare("database"))
      if (!_create()) { 
        _error();
        return false;
      }

    // CREATE TABLE
    if (!obj.compare("table")) 
      if (!_createTable()) { 
        _error();
        return false;
      } 
    
  }
  
  //DROP
  if (!keyWord.compare("drop")) {

    // DROP DATABASE
    if (!obj.compare("database"))
      if (!_drop()) {
        _error();
        return false;
      }

    // DROP TABLE
    if (!obj.compare("table")) 
      if (!_droptable()) {
        _error();
        return false;
      }
  }

  // USE
  if (!keyWord.compare("use")) {
    if (!_use()) {
      _error();
      return false;
    }
  }

  // INSERT
  if (!keyWord.compare("insert")) {
    if (!_insert()) {
      _error();
      return false;
    }
  }
  // Todo

  _Destory();
  return true;
}

void command::_Destory() {
  //Todo
}